using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using GameFramework;
using GameFramework.Resource;
using UnityEditor;
using UnityEngine;
using UnityGameFramework;
using UnityGameFramework.Runtime;
using XLua;

public class LuaComponent : GameFrameworkComponent
{
    [SerializeField]
    private bool mEditorMode = true;
    private LuaEnv _env;
    private bool _successInitFlag = false;
    private Dictionary<int, byte[]> _luaBytesMap;  
    
    public LuaEnv Env => _env;
    public bool InitFlag => _successInitFlag;

    protected override void Awake()
    {
        base.Awake();
        _luaBytesMap = new Dictionary<int, byte[]>();
        _env = new LuaEnv();
        _env.AddLoader(LuaLoader);
    }

    private void Update()
    {
        _env.Tick();
       // _env.GC();
    }

    public void LoadLua()
    {
        if (_successInitFlag)
            return;

        if (mEditorMode)
        {
            LoadEditorMode();
            return;
        }

        EntityInst.Resource.LoadBinary("Assets/RuntimeResources/Lua",
            new LoadBinaryCallbacks(OnLoadBinarySuccessCallback, OnLoadBinaryFailureCallback), this);
    }

    public void DoString(string fileName,string chunkName,LuaTable table)
    {
        var module = LoadFileModule(fileName);
        _env.DoString(module, chunkName, table);
    }

    public byte[] LoadFileModule(string fileName)
    {
        fileName = fileName.Replace('.', '/');
        var path = Utility.Path.GetRegularPath(AssetUtility.GetLua(fileName));
        if(_luaBytesMap.TryGetValue(path.GetHashCode(),out var x))
            return x;
        throw new Exception($"LoadFileModule exception, filepath = {path}");
    }

    private void LoadEditorMode()
    {
        var path = System.IO.Path.Combine(Application.dataPath, "RuntimeResources/Lua");
        var files= System.IO.Directory.GetFiles(path, "*", SearchOption.AllDirectories);
        
        foreach (var file in files)
        {
            if (file.EndsWith(".meta") || !file.EndsWith(".lua.txt"))
                continue;
            var bytes = System.IO.File.ReadAllBytes(file);
            var p = Utility.Path.GetRegularPath(file.Replace(Application.dataPath, "Assets"));
            _luaBytesMap.Add(p.GetHashCode(), bytes);
        }

        _successInitFlag = true;
    }

    private void OnDestroy()
    {
        _env.Dispose();
    }

    private byte[] LuaLoader(ref string filepath)
    {
        filepath = filepath.Replace('.', '/');
        var finalPath = Utility.Path.GetRegularPath(AssetUtility.GetLua(filepath));
        if (_luaBytesMap.TryGetValue(finalPath.GetHashCode(), out var x))
        {
            Debug.Log("return file ---- "+filepath);
            return x;
        }

        throw new Exception($"lua loader exception, filepath = {finalPath}");
    }

    private void OnLoadBinarySuccessCallback(string binaryAssetName, byte[] binaryBytes, float duration, object userData)
    {
        if (userData != this)
            return;
        _successInitFlag = true;
        //启动加载lua二进制包， 反序列二进制包，取出里头所有byte[]
    }

    private void OnLoadBinaryFailureCallback(string binaryAssetName, LoadResourceStatus status, string errorMessage, object userData)
    {
        if (userData != this)
            return;

        throw new Exception($"load lua binary asset error, path = {binaryAssetName}");
    }
}